package edu.rit.drh4818.raytracing.awt;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;

import edu.rit.drh4818.raytracing.light.ColorMixer;
import edu.rit.drh4818.raytracing.util.Ray;
import edu.rit.drh4818.raytracing.util.Scene;
import edu.rit.drh4818.raytracing.util.SuperSampling;


/**
 * Renderer which computes the color values of the screen using ray tracing.
 * 
 * @author Darren Headrick
 *
 */
@SuppressWarnings("serial")
public class RayTracingRenderer extends JPanel 
{
	
	/**
	 * The last rendered scene.
	 */
	private Color[][] scene;
	
	/**
	 * Create new RayTracing renderer.
	 *  A ray source is added in the center of the screen.
	 *  
	 *  If supersampling is enabled, then additional ray spawns are added.
	 * 
	 */
	public RayTracingRenderer()
	{
		setPreferredSize( 
				new Dimension( 
						(int)(Scene.instance.screenX), 
						(int)(Scene.instance.screenY) ) );
		scene = new Color[ Scene.instance.screenX ][ Scene.instance.screenY ];
		render();
	}
	
	/*
	 * Paints the last rendered scene.
	 */
	public void paint( Graphics g )
	{
		// render all of the computed colors
		for( int x = 0; x < scene.length; x++ )
		{
			for( int y = 0; y < scene[x].length; y++ )
			{
				if( scene[x][y] != null )
				{
					g.setColor( scene[x][y] );
					g.drawLine(x,y,x,y);
				}
			}
		}
	}
	
	/**
	 * Render the scene.
	 */
	public void render() 
	{	

		long timing = - System.currentTimeMillis();
		
		// for each pixel on the screen
		for( int x = 0; x < Scene.instance.screenX; x++ )
		{
			for( int y = 0; y < Scene.instance.screenY; y++ )
			{
				if( scene[x][y] == null ) { scene[x][y] = new Color(0,0,0); }
				Ray source = 
					Ray.rayFromPoints( Scene.instance.eyex, Scene.instance.eyey, Scene.instance.eyez,
						x, y, Scene.instance.screenZ );
				
				if( Scene.instance.SUPERSAMPLING )
				{
					scene[x][y] = ColorMixer.add( 
							scene[x][y], 
							SuperSampling.getColor(source, 1000000, 1, 1 ) );
				} 
				else
				{
					scene[x][y] = source.findNearestIntersection().getColor( 1 );
				}
			}
		}
		
		// print out the render time.
		timing += System.currentTimeMillis();
		System.out.println( "Render time = " + timing + " msec" );
		
		if( Scene.instance.tone != null )
		{
			scene = Scene.instance.tone.transform( scene );
		}
		repaint();
	}	
}
